package handler

import (
	"context"
	"fmt"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/ptypes/wrappers"
	"github.com/jinzhu/gorm"
	"math"
	"strings"
	"time"

	"kop/framework/broker"
	context2 "kop/framework/context"
	"kop/framework/errors"
	"kop/libs/database"
	"kop/modules/activity/first_pay"
	"kop/modules/configuration/configuration/attribute/attrtype"
	"kop/modules/configuration/configuration/keyword"
	"kop/modules/item/consts"
	"kop/modules/role/configuration"
	"kop/modules/role/configuration/level"
	"kop/modules/role/entity"
	"kop/modules/role/models"
	"kop/modules/stage/configuration/event"
	"kop/pb"
	"kop/pb/service"
	"kop/util/date"
	"kop/util/rand"

	activityC "kop/modules/activity/client"
	awardM "kop/modules/award/models"
	captainC "kop/modules/captain/client"
	itemC "kop/modules/item/client"
	maidC "kop/modules/maid/client"
	moneyC "kop/modules/money/client"
	questC "kop/modules/quest/client"
)

type RoleServiceHandler struct {
	context2.Context
}

func (h *RoleServiceHandler) GetByUserID(_ context.Context, req *service.GetByUserIDRequest, resp *pb.RoleResp) error {

	var role = entity.Role{
		UserID:   req.UserID,
		ServerID: req.ServerID,
		Name:     "",
		Level:    0,
		Photo:    11000,
		Clothing: 12000,
		Power:    6000,
		//SignInDate:  date.Date(time.Now()),
		//SignInNum: 0,
	}

	if err := database.DB.Where(entity.Role{UserID: role.UserID, ServerID: role.ServerID}).FirstOrCreate(&role).Error; err != nil {
		return err
	}

	//if role.SignInDate != date.Date(time.Now()) {
	//	role.SignInDate = date.Date(time.Now())
	//	role.SignInNum += 1
	//	_ = models.Save(database.DB, &role)
	//}

	resp.Role = models.BuildPbRole(&role)
	resp.CreateTime = role.CreatedAt.Unix()
	return nil
}

func (h *RoleServiceHandler) GetRole(_ context.Context, req *service.RoleRequest, resp *service.Role) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if ok {
		resp.Role = models.BuildPbRole(role)
	}

	return nil
}

func (h *RoleServiceHandler) GetRoles(_ context.Context, req *pb.Int32Slice, resp *pb.Roles) error {

	resp.Roles = models.GetRoles(database.DB, req.Slices)
	return nil
}

func (h *RoleServiceHandler) GetVIP(_ context.Context, req *service.RoleRequest, resp *service.VIP) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if !ok {
		return errors.ParamError
	}

	var conf = configuration.GetByVIP(role.VIP)
	resp.VIP = role.VIP
	resp.Drink = conf.Drink
	resp.Date = conf.Date
	resp.Wish = conf.Wish
	resp.Date = conf.Date
	resp.Benediction = conf.Benediction
	return nil
}

func (h *RoleServiceHandler) LevelUp(ctx context.Context, _ *empty.Empty, resp *pb.LevelUpResp) error {

	var role, ok = models.GetRole(database.DB, h.GetRoleID(ctx))
	if !ok {
		return errors.ParamError
	}

	var conf, _ = level.GetByRoleLevel(role.Level)
	if conf.NeedIncome == 0 {
		return errors.ParamError
	}

	//if role.Exp < conf.NeedRenown {
	//	return errors.ParamError
	//}

	if conf.NeedIncome > moneyC.GetIncome(role.RoleID) {
		return errors.CoinNotEnoughError
	}

	var item, err = itemC.DelItem(role.RoleID, h.GetServerID(ctx), consts.RoleExp, conf.NeedRenown)
	if err != nil {
		return err
	}

	role.Level += 1
	models.Save(database.DB, role)

	conf, _ = level.GetByRoleLevel(role.Level)
	resp.Role = models.BuildPbRole(role)
	resp.Award = awardM.RandAward(resp.Role, conf.AwardID)

	_ = awardM.SendAward(resp.Role, resp.Award)

	questC.RoleLevel(role.RoleID, role.Level)
	_ = broker.RolePublish(role.RoleID, pb.WsCode_CodeItem, item)

	// 提督爵位晋升：提督[提督名称七个字]实力超群，晋升为[爵位名称]！
	_ = broker.ServerPublish(h.GetServerID(ctx), pb.WsCode_CodeMessage, &pb.ServerMessage{Type: 1, Name: []string{role.Name}, Nums: []int32{role.Level}})
	return nil
}

//func (h *RoleServiceHandler) AddExp(_ context.Context, req *service.DefaultRequest, resp *pb.Role) error {
//
//	var role, ok = models.GetRole(database.DB, req.RoleID)
//	if !ok {
//		return errors.ParamError
//	}
//
//	role.Exp += req.Value
//	models.Save(database.DB, role)
//
//	*resp = *models.BuildPbRole(role)
//	return nil
//}

//func (h *RoleServiceHandler) IsDailyDiamond(ctx context.Context, req *service.RoleRequest, resp *wrappers.BoolValue) error {
//
//	resp.Value = models.GetDailyGift(database.DB, req.RoleID).IsDailyDiamond()
//	return nil
//}

// 收钻石
//func (h *RoleServiceHandler) UpdateDailyDiamond(ctx context.Context, req *service.RoleRequest, empty *empty.Empty) error {
//
//	return models.UpdateDailyDiamond(database.DB, req.RoleID)
//}

const EventRefreshSec = 30 * 60 // 30分钟回复1个事件

// 事件
func (h *RoleServiceHandler) GetEvents(_ context.Context, req *service.RoleRequest, resp *pb.Int32Slice) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if !ok {
		return errors.ParamError
	}

	roleConf, err := level.GetByRoleLevel(role.Level)
	if err != nil {
		return err
	}

	roleEvent, err := models.GetRoleEvent(database.DB, req.RoleID)
	if err != nil {
		roleEvent = &entity.RoleEvent{RoleID: req.RoleID}

		for i := 0; i < roleConf.EventCount; i++ {
			var newEvent = h.randEvent(roleEvent.EventIDArr, roleConf.EventCount)
			roleEvent.EventIDArr = append(roleEvent.EventIDArr, newEvent)
		}

		models.CreateRoleEvent(database.DB, roleEvent)
	}

	var save = false

	var now = time.Now().Unix()

	// 计算回复时间
	for {

		if len(roleEvent.EventIDArr) >= roleConf.EventCount {
			break
		}

		if now >= roleEvent.RefreshTime+EventRefreshSec {
			var newEvent = h.randEvent(roleEvent.EventIDArr, roleConf.EventCount)
			roleEvent.EventIDArr = append(roleEvent.EventIDArr, newEvent)
			roleEvent.RefreshTime += EventRefreshSec
			save = true
		} else {
			break
		}
	}

	if save {

		if len(roleEvent.EventIDArr) >= roleConf.EventCount {
			roleEvent.RefreshTime = 0
		}

		models.SaveRoleEvent(database.DB, roleEvent)
	}

	resp.Slices = roleEvent.EventIDArr
	return nil
}

func (h *RoleServiceHandler) Event1(_ context.Context, req *service.DefaultRequest, resp *service.RoleEventResp) error {

	var conf, err = configuration.GetByEventID(req.Value)
	if err != nil {
		return err
	}

	if conf.EventType != configuration.Type1 {
		return errors.New("事件类型错误")
	}

	roleEvent, err := h.delEvent(req.RoleID, req.Value)
	if err != nil {
		return err
	}

	resp.AwardID = conf.AwardID[0]
	resp.EventIDs = roleEvent.EventIDArr

	return nil
}

func (h *RoleServiceHandler) Event2(_ context.Context, req *service.RoleEvent2Request, resp *service.RoleEventResp) error {

	if req.Answer < 0 {
		return errors.ParamError
	}

	var conf, err = configuration.GetByEventID(req.EventID)
	if err != nil {
		return err
	}

	if conf.EventType != configuration.Type2 {
		return errors.New("事件类型错误")
	}

	if req.Answer > int32(len(conf.AwardID))-1 {
		return errors.ParamError
	}

	roleEvent, err := h.delEvent(req.RoleID, req.EventID)
	if err != nil {
		return err
	}

	resp.AwardID = conf.AwardID[0]
	resp.EventIDs = roleEvent.EventIDArr
	return nil
}

func (h *RoleServiceHandler) Event3(_ context.Context, req *service.RoleEvent3Request, resp *service.RoleEvent3Resp) error {

	var conf, err = event.GetEventByID(req.EventID)
	if err != nil {
		return err
	}

	if conf.EventType != event.Type3 {
		return errors.New("事件类型错误")
	}

	resp.Success = true

	if conf.NeedCamp > 0 && req.Captain.Camp != conf.NeedCamp {
		resp.Success = false
	} else if conf.NeedSex > 0 && req.Captain.Sex != conf.NeedSex {
		resp.Success = false
	}

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if !ok {
		return errors.ParamError
	}

	roleConf, err := level.GetByRoleLevel(role.Level)
	if err != nil {
		return err
	}

	if resp.Success {
		switch conf.NeedAttribute {
		case attrtype.TypeINT:

			var rate = float32(req.Captain.Attribute.INT) / float32(roleConf.StandardINT)
			if rate < 0.2 {
				rate = 0.2
			}

			resp.Success = rand.IsWin(rate)

		case attrtype.TypeCOR:

			var rate = float32(req.Captain.Attribute.COR) / float32(roleConf.StandardCOR)
			if rate < 0.2 {
				rate = 0.2
			}

			resp.Success = rand.IsWin(rate)

		case attrtype.TypeCHR:

			var rate = float32(req.Captain.Attribute.CHR) / float32(roleConf.StandardCHR)
			if rate < 0.2 {
				rate = 0.2
			}

			resp.Success = rand.IsWin(rate)
		}
	}

	if resp.Success {
		resp.AwardID = conf.AwardID[0]
	} else {
		resp.AwardID = conf.AwardID[1]
	}

	roleEvent, err := h.delEvent(req.RoleID, req.EventID)
	if err != nil {
		return err
	}

	resp.EventIDs = roleEvent.EventIDArr
	return nil
}

func (h *RoleServiceHandler) GetDeclaration(_ context.Context, req *service.RoleRequest, resp *wrappers.StringValue) error {

	return database.DB.Table("roles").Select("declaration as \"value\"").Where("role_id = ?", req.RoleID).First(resp).Error
}

func (h *RoleServiceHandler) SetDeclaration(ctx context.Context, req *wrappers.StringValue, _ *empty.Empty) error {

	if len([]rune(req.Value)) > 64 {
		return errors.ParamError
	}

	return database.DB.Table("roles").Where("role_id = ?", h.GetRoleID(ctx)).Update("declaration", req.Value).Error
}

func (h *RoleServiceHandler) UpdatePower(_ context.Context, req *service.Int64Request, _ *empty.Empty) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if ok {

		var up = req.Value - role.MaxPower

		role.Power = req.Value
		if role.Power > role.MaxPower {
			role.MaxPower = role.Power
		}

		models.Save(database.DB, role)

		questC.Power(role.RoleID, role.Power)

		if up > 0 {
			activityC.AddPoints(role.RoleID, role.ServerID, activityC.Power, up)
		}
	}

	return nil
}

func (h *RoleServiceHandler) GetSignIn(ctx context.Context, _ *empty.Empty, resp *pb.SignInResp) error {

	var roleID = h.GetRoleID(ctx)
	var role = &pb.Role{RoleID: roleID}

	var data = models.GetSignIn(database.DB, roleID)
	if data.Date == date.Date(time.Now()) {
		resp.SignIn = true
	}

	resp.Number = data.Number
	resp.Awards = make([]*pb.Award, 0, len(configuration.SignInConfigs))
	for _, v := range configuration.SignInConfigs {

		resp.Awards = append(resp.Awards, awardM.RandAward(role, v.AwardID))
	}

	return nil
}

// 签到活动
func (h *RoleServiceHandler) SignIn(ctx context.Context, _ *empty.Empty, resp *pb.Award) error {

	var roleID = h.GetRoleID(ctx)

	var signIn = models.GetSignIn(database.DB, roleID)
	if signIn.Date == date.Date(time.Now()) {
		return errors.ParamError
	}

	signIn.Date = date.Date(time.Now())
	signIn.Number += 1

	conf, err := configuration.GetSignInConf(signIn.Number)
	if err != nil {
		return err
	}

	err = database.DB.Save(signIn).Error
	if err == nil {

		var role = &pb.Role{RoleID: roleID}

		*resp = *awardM.RandAward(role, conf.AwardID)
		err = awardM.SendAward(role, resp)
		// quest
		questC.Login(roleID)
	}

	return err
}

func (h *RoleServiceHandler) GetMonthCard(_ context.Context, req *service.RoleRequest, resp *pb.MonthCardResp) error {

	var monthCard = models.GetMonthCard(database.DB, req.RoleID)
	resp.MonthCard = &pb.MonthCard{
		Expire: int32(math.Max(0, float64(monthCard.MonthCardDate.Unix()))),
		Day:    int32(math.Max(monthCard.MonthCardDate.Sub(time.Now()).Hours()/24, 0)),
	}
	resp.YearCard = &pb.MonthCard{
		Expire: int32(math.Max(0, float64(monthCard.YearCardDate.Unix()))),
		Day:    int32(math.Max(monthCard.YearCardDate.Sub(time.Now()).Hours()/24, 0)),
	}
	return nil
}

//func (h *RoleServiceHandler) BuyMonthCard(ctx context.Context, req *service.RoleRequest, resp *pb.MonthCard) error {
//
//	var monthCard, err = models.GetMonthCard(database.DB, req.RoleID)
//	if err != nil {
//		return err
//	}
//
//	var Date = time.Now().AddDate(0, 0, 30)
//	monthCard.MonthCardDate = time.Date(Date.Year(), Date.Month(), Date.Day(), 23, 59, 59, 0, time.Local)
//
//	err = database.DB.Save(monthCard).Error
//	if err == nil {
//
//		resp.Day = 30
//		resp.Expire = int32(monthCard.MonthCardDate.Unix())
//
//		questC.DailyMonthCard(req.RoleID)
//	}
//
//	return err
//}
//
//func (h *RoleServiceHandler) BuyYearCard(ctx context.Context, req *service.RoleRequest, resp *pb.MonthCard) error {
//
//	var monthCard, err = models.GetMonthCard(database.DB, req.RoleID)
//	if err != nil {
//		return err
//	}
//
//	var Date = time.Now().AddDate(0, 0, 365)
//	monthCard.YearCardDate = time.Date(Date.Year(), Date.Month(), Date.Day(), 23, 59, 59, 0, time.Local)
//
//	resp.Day = 365
//	resp.Expire = int32(monthCard.MonthCardDate.Unix())
//
//	err = database.DB.Save(monthCard).Error
//	if err == nil {
//
//		resp.Day = 30
//		resp.Expire = int32(monthCard.YearCardDate.Unix())
//
//		questC.DailyYearCard(req.RoleID)
//	}
//
//	return err
//}

func (h *RoleServiceHandler) Day7(ctx context.Context, _ *empty.Empty, resp *pb.Day7Resp) error {

	var day7 = models.GetDay7(database.DB, h.GetRoleID(ctx))
	var year, month, day = day7.UpdatedAt.Date()
	var nowYear, nowMonth, nowDay = time.Now().Date()

	if year != nowYear || month != nowMonth || day != nowDay && day7.Day < 7 {
		day7.Day += 1
		models.SaveDay7(database.DB, &day7)
	}

	resp.Day7Awards = make([]*pb.Day7Award, 0, 7)
	for day := int32(1); day <= 7; day++ {

		var conf = configuration.GetDay7Conf(day)

		var day7Award = pb.Day7Award{
			CaptainID: conf.CaptainID,
			MaidID:    conf.MaidID,
			Items:     make([]*pb.RawItem, 0, 4),
			State:     pb.State_Default,
		}

		if day7.Day >= day {
			if day7.GetRecord(day) {
				day7Award.State = pb.State_Finish
			} else {
				day7Award.State = pb.State_Doing
			}
		}

		day7Award.Items = append(day7Award.Items, &pb.RawItem{ItemID: conf.ItemID1, Number: conf.ItemCount1})
		day7Award.Items = append(day7Award.Items, &pb.RawItem{ItemID: conf.ItemID2, Number: conf.ItemCount2})
		if conf.ItemID3 > 0 {
			day7Award.Items = append(day7Award.Items, &pb.RawItem{ItemID: conf.ItemID3, Number: conf.ItemCount3})
		}
		if conf.ItemID4 > 0 {
			day7Award.Items = append(day7Award.Items, &pb.RawItem{ItemID: conf.ItemID4, Number: conf.ItemCount4})
		}

		resp.Day7Awards = append(resp.Day7Awards, &day7Award)
	}

	return nil
}

func (h *RoleServiceHandler) GetDay7Awards(ctx context.Context, req *wrappers.Int32Value, resp *pb.GetDay7AwardsResp) error {

	if req.Value > 7 {
		return errors.ParamError
	}

	var days = req.Value
	var roleID = h.GetRoleID(ctx)
	var day7 = models.GetDay7(database.DB, roleID)

	var year, month, day = day7.UpdatedAt.Date()
	var nowYear, nowMonth, nowDay = time.Now().Date()

	if year != nowYear || month != nowMonth || day != nowDay && day7.Day < 7 {
		day7.Day += 1
	}

	if day7.Day < days {
		return errors.ParamError
	}

	if day7.GetRecord(days) {
		return nil
	}

	day7.SetRecord(days)
	models.SaveDay7(database.DB, &day7)

	var award = &pb.Award{}

	var conf = configuration.GetDay7Conf(days)
	if conf.CaptainID > 0 {

		var res = captainC.CreateCaptain(ctx, conf.CaptainID)
		if v, ok := res.CaptainOrPiece.(*pb.CreateCaptainResp_Captain); ok {
			resp.Captain = v.Captain
		}

		if v, ok := res.CaptainOrPiece.(*pb.CreateCaptainResp_AwardItem); ok {
			defer func() {
				resp.Items = append(resp.Items, v.AwardItem)
			}()
		}
	}

	if conf.MaidID > 0 {
		var err error
		if resp.Maid, err = maidC.Create(roleID, conf.MaidID); err != nil {
			return err
		}
	}

	award.AddRawItem(&pb.RawItem{ItemID: conf.ItemID1, Number: conf.ItemCount1})
	award.AddRawItem(&pb.RawItem{ItemID: conf.ItemID2, Number: conf.ItemCount2})

	if conf.ItemID3 > 0 {
		award.AddRawItem(&pb.RawItem{ItemID: conf.ItemID3, Number: conf.ItemCount3})
	}
	if conf.ItemID4 > 0 {
		award.AddRawItem(&pb.RawItem{ItemID: conf.ItemID4, Number: conf.ItemCount4})
	}

	resp.Items = award.AwardItems
	return awardM.SendAward(&pb.Role{RoleID: roleID}, award)
}

// 查询充值钻石与是否领取首充奖励
func (h *RoleServiceHandler) GetPay(ctx context.Context, _ *empty.Empty, resp *service.RolePayResp) error {

	var pay = models.GetRolePay(database.DB, h.GetRoleID(ctx))
	resp.Diamond = pay.Diamond
	resp.GetFirstPayAward = pay.GetFirstPay

	return nil
}

func (h *RoleServiceHandler) GetFirstPayAwards(ctx context.Context, _ *empty.Empty, resp *pb.FirstPayResp) error {

	var roleID = h.GetRoleID(ctx)
	var pay = models.GetRolePay(database.DB, roleID)
	if pay.GetFirstPay {
		return nil
	}

	if pay.Diamond <= 0 {
		return errors.ParamError
	}

	pay.GetFirstPay = true
	models.SaveRolePay(database.DB, &pay)

	var role = pb.Role{RoleID: roleID}
	*resp = *first_pay.FirstPayResp(&role)

	var res = captainC.CreateCaptain(ctx, resp.Captain.CaptainID)

	if v, ok := res.CaptainOrPiece.(*pb.CreateCaptainResp_Captain); ok {

		resp.Captain = v.Captain

	} else if v, ok := res.CaptainOrPiece.(*pb.CreateCaptainResp_AwardItem); ok {

		resp.Captain = nil

		defer func() {
			resp.Award.AwardItems = append(resp.Award.AwardItems, v.AwardItem)
		}()
	}

	resp.State = pb.State_Finish
	return awardM.SendAward(&role, resp.Award)
}

func (h *RoleServiceHandler) PaySuccess(_ context.Context, req *service.PaySuccessRequest, _ *empty.Empty) (err error) {

	var session = database.DB.Begin()
	if session.Error != nil {
		return session.Error
	}

	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
		if err != nil {
			session.Rollback()
		}
	}()

	var pay = models.GetRolePay(session, req.RoleID)

	pay.Diamond += req.Product.Diamond
	models.SaveRolePay(session, &pay)

	var role, ok = models.GetRole(session, req.RoleID)
	if !ok {
		return errors.ParamError
	}

	var VIPLv = configuration.GetVIPByDiamond(pay.Diamond)

	if role.VIP < VIPLv {
		// 这样子写是避免异步并发覆盖数据问题
		if err = session.Table("roles").Where("role_id = ?", req.RoleID).Update("vip", VIPLv).Error; err != nil {
			return err
		}
	}

	var diamond = req.Product.Diamond
	if req.Product.Double {
		diamond *= 2
	}

	// 月卡or年卡设置到期时间
	switch req.Product.Type {
	case pb.ProductType_Product_MonthCard:

		var Date = time.Now().AddDate(0, 0, 30)
		var monthCard = models.GetMonthCard(session, req.RoleID)
		monthCard.MonthCardDate = time.Date(Date.Year(), Date.Month(), Date.Day(), 23, 59, 59, 0, time.Local)

		models.SaveMonthCard(session, monthCard)

	case pb.ProductType_Product_YearCard:

		var Date = time.Now().AddDate(0, 0, 365)
		var monthCard = models.GetMonthCard(database.DB, req.RoleID)
		monthCard.YearCardDate = time.Date(Date.Year(), Date.Month(), Date.Day(), 23, 59, 59, 0, time.Local)

		models.SaveMonthCard(session, monthCard)
	}

	if err = session.Commit().Error; err != nil {
		return err
	}

	switch req.Product.Type {
	case pb.ProductType_Product_MonthCard:

		questC.DailyMonthCard(req.RoleID)

	case pb.ProductType_Product_YearCard:

		questC.DailyYearCard(req.RoleID)
	}

	// 还要发钻石
	var item = itemC.AddItem(req.RoleID, consts.Diamond, diamond)
	_ = broker.RolePublish(req.RoleID, pb.WsCode_CodeItem, item)
	return nil
}

func (h *RoleServiceHandler) GetMaxPower(_ context.Context, req *service.RoleRequest, resp *wrappers.Int64Value) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if !ok {
		return errors.ParamError
	}
	resp.Value = role.MaxPower
	return nil
}

// events 现有的事件ID
// 爵位的对应的事件最大数量
func (h *RoleServiceHandler) randEvent(events []int32, maxNum int) int32 {

	var typeNumMap = make(map[configuration.EventType]int, 3)

	for _, eventID := range events {
		conf, _ := configuration.GetByEventID(eventID)
		typeNumMap[conf.EventType] += 1
	}

	var configs []rand.Value
	for _, conf := range configuration.EventConfigs {

		var find = false
		for _, eventID := range events {
			if eventID == conf.EventID {
				find = true
			}
		}

		if find {
			continue
		}

		if typeNumMap[conf.EventType] < maxNum/2 {
			configs = append(configs, conf)
		}
	}

	return rand.WithWeight(configs, 1)[0].GetID()
}

// 删除完成的事件
func (h *RoleServiceHandler) delEvent(roleID, delID int32) (*entity.RoleEvent, error) {

	var roleEvent, err = models.GetRoleEvent(database.DB, roleID)
	if err != nil {
		return roleEvent, err
	}

	var find = false
	var news []int32

	for _, eventID := range roleEvent.EventIDArr {
		if delID == eventID {
			find = true
		} else {
			news = append(news, eventID)
		}
	}

	if !find {
		return roleEvent, errors.New("未触发对应的事件")
	}

	roleEvent.EventIDArr = news

	if roleEvent.RefreshTime == 0 {
		// 如果之前事件数量是满的 现在开始计数
		roleEvent.RefreshTime = time.Now().Unix()
	}

	models.SaveRoleEvent(database.DB, roleEvent)
	return roleEvent, nil
}

func (h *RoleServiceHandler) WorshipDiamond(_ context.Context, req *service.RoleRequest, resp *wrappers.Int32Value) error {

	var role, ok = models.GetRole(database.DB, req.RoleID)
	if !ok {
		return errors.ParamError
	}

	var c, err = level.GetByRoleLevel(role.Level)
	if err == nil {
		resp.Value = c.AwardDiamond
	}

	return err
}

func (h *RoleServiceHandler) Ranking(_ context.Context, req *wrappers.Int32Value, resp *service.RankingPointsList) error {

	var data []entity.Role

	database.DB.Where("server_id = ? AND power > 0", req.Value).Order("power DESC, updated_at ASC").Limit(200).Find(&data)

	resp.Ranking = make([]*service.RankingPoints, 0, len(data))
	for _, v := range data {
		resp.Ranking = append(resp.Ranking, &service.RankingPoints{RoleID: v.RoleID, Points: v.Power})
	}

	return nil
}

func (h *RoleServiceHandler) MyRanking(ctx context.Context, _ *empty.Empty, resp *pb.RankingNumber) (err error) {

	var role, _ = models.GetRole(database.DB, h.GetRoleID(ctx))

	var number int32
	database.DB.Model(&role).Where("server_id = ? AND power > ?", h.GetServerID(ctx), role.Power).Count(&number)

	resp.Points = role.Power
	resp.Number = number + 1
	return nil
}

func (h *RoleServiceHandler) SetName(ctx context.Context, req *pb.SetNameRequest, resp *wrappers.Int32Value) error {

	if len(req.Name) == 0 || len(req.Name) > 21 {
		return errors.ParamError
	}

	if req.Sex != 0 && req.Sex != 1 {
		return errors.ParamError
	}

	for _, v := range keyword.KeyWords {
		if strings.Contains(req.Name, v) {
			resp.Value = 2 // 敏感
			return nil
		}
	}

	var n int
	if err := database.DB.Table("roles").Where("name = ?", req.Name).Count(&n).Error; err != nil {
		return err
	}

	if n > 0 {
		resp.Value = 1 // 重名
		return nil
	}

	var roleID = h.GetRoleID(ctx)
	var role, _ = models.GetRole(database.DB, roleID)
	if role.Name != req.Name {

		if role.Name != "" {
			const ItemID = 101311 // 改名卡
			if err := itemC.AsyncDelItem(roleID, 0, ItemID, 1); err != nil {
				return err
			}
		} else {
			role.Sex = req.Sex
			role.Photo = req.Sex // 头像先和性别一样
		}

		role.Name = req.Name
		models.Save(database.DB, role)
	}

	return nil
}

func (h *RoleServiceHandler) VIPAwards(ctx context.Context, _ *empty.Empty, resp *pb.VIPAwards) error {

	var data = models.GetRolePay(database.DB, h.GetRoleID(ctx))

	resp.Diamond = data.Diamond
	resp.Awards = data.GetVIPRecord()
	return nil
}

func (h *RoleServiceHandler) GetVIPAward(ctx context.Context, req *wrappers.Int32Value, resp *pb.Award) error {

	var role, _ = models.GetRole(database.DB, h.GetRoleID(ctx))

	if req.Value > role.VIP {
		return errors.ParamError
	}

	var data = models.GetRolePay(database.DB, h.GetRoleID(ctx))

	if _, ok := data.GetVIPRecord()[req.Value]; ok {
		return errors.ParamError
	}

	data.SetVIPRecord(req.Value)
	models.SaveRolePay(database.DB, &data)

	*resp = *awardM.GetByAwardID(h.GetRoleID(ctx), configuration.GetByVIP(req.Value).AwardID)
	return nil
}

func (h *RoleServiceHandler) GetProgress(ctx context.Context, _ *empty.Empty, resp *wrappers.StringValue) error {

	var data entity.Progress

	database.DB.First(&data, h.GetRoleID(ctx))
	resp.Value = data.Data
	return nil
}

func (h *RoleServiceHandler) SetProgress(ctx context.Context, req *wrappers.StringValue, _ *empty.Empty) error {

	if len([]rune(req.Value)) > 10000 {
		return fmt.Errorf("string too long")
	}

	var data = &entity.Progress{RoleID: h.GetRoleID(ctx)}

	if database.DB.First(data).Error == gorm.ErrRecordNotFound {

		data.Data = req.Value
		return database.DB.Create(data).Error

	} else {

		data.Data = req.Value
		return database.DB.Save(data).Error
	}
}

func (h *RoleServiceHandler) Online(_ context.Context, req *service.RoleRequest, _ *empty.Empty) error {

	var data = models.GetOnline(req.RoleID)
	data.OnlineTime = time.Now()

	return models.SaveOnline(&data)
}

func (h *RoleServiceHandler) Offline(_ context.Context, req *service.RoleRequest, _ *empty.Empty) error {

	var data = models.GetOnline(req.RoleID)
	data.OfflineTime = time.Now()

	return models.SaveOnline(&data)
}

func (h *RoleServiceHandler) SaveOnlineNum(_ context.Context, req *wrappers.Int32Value, _ *empty.Empty) error {

	return database.DB.Create(&entity.OnlineStatistics{Num: req.Value}).Error
}
